package com.zft.userwalletmanager.application.handler;

import com.zft.userwalletmanager.application.service.AccountFlowService;
import com.zft.userwalletmanager.application.service.WalletService;
import com.zft.userwalletmanager.domain.bo.WalletBO;
import com.zft.userwalletmanager.infrastructure.common.enums.ResultCode;
import com.zft.userwalletmanager.infrastructure.common.enums.WalletStatusEnums;
import com.zft.userwalletmanager.infrastructure.common.exception.BizException;
import com.zft.userwalletmanager.infrastructure.gateway.database.model.AccountFlowDO;
import com.zft.userwalletmanager.infrastructure.gateway.database.model.WalletDO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.Objects;

@Service
public class WalletHandler {
    @Autowired
    private WalletService walletService;
    @Autowired
    private AccountFlowService accountFlowService;

    /**
     * 获取钱包余额
     * @param walletBO
     * @return
     */
    public Long getBalance(WalletBO walletBO) {
        WalletDO walletDO = walletService.selectWalletByUserId(walletBO.getUserId(),false);
        if (Objects.isNull(walletDO)) {
            throw new BizException(ResultCode.WALLET_INFO_IS_NULL);
        }
        return walletDO.getWalletBalance();
    }

    /**
     * 扣款事务
     * @param walletBO
     * @return
     */
    @Transactional
    public void credit(WalletBO walletBO) {
        WalletDO walletDO = walletService.selectWalletByUserId(walletBO.getUserId(),true);
        if (Objects.isNull(walletDO)) {
            throw new BizException(ResultCode.WALLET_INFO_IS_NULL);
        }
        if (WalletStatusEnums.FROZEN.equals(walletDO.getWalletStatus())) {
            throw new BizException(ResultCode.WALLET_STATUS_IS_FROZEN);
        }
        if (!walletDO.getWalletCurrency().equals(walletBO.getCurrency())) {
            throw new BizException(ResultCode.CURRENCY_IS_NOT_SAME);
        }
        if (walletDO.getWalletBalance() < walletBO.getAmount()) {
            throw new BizException(ResultCode.BALANCE_IS_NOT_ENOUGH);
        }
        Long newBalance = walletDO.getWalletBalance() - walletBO.getAmount();
        walletBO.setEndingBalance(newBalance);
        walletBO.setWalletNo(walletDO.getWalletNo());
        try {
            accountFlowService.insertAccountFlow(walletBO);
        } catch (DuplicateKeyException e) {
            AccountFlowDO accountFlowDO = accountFlowService.selectAccountFlowByOrderId(walletBO.getOrderId());
            if (!walletBO.getWalletNo().equals(accountFlowDO.getWalletNo())) {
                throw new BizException(ResultCode.ACCOUNT_INCONSISTENT_CORE_PARAMETERS);
            }
            if (!walletBO.getType().equals(accountFlowDO.getType())) {
                throw new BizException(ResultCode.ACCOUNT_INCONSISTENT_CORE_PARAMETERS);
            }
            if (!walletBO.getAmount().equals(accountFlowDO.getAmount())) {
                throw new BizException(ResultCode.ACCOUNT_INCONSISTENT_CORE_PARAMETERS);
            }
            if (!walletBO.getCurrency().equals(accountFlowDO.getCurrency())) {
                throw new BizException(ResultCode.ACCOUNT_INCONSISTENT_CORE_PARAMETERS);
            }
        }
        int i = walletService.updateWalletBalance(walletBO.getUserId(), newBalance);
        if (i != 1) {
            throw new BizException(ResultCode.BALANCE_UPDATE_FAIL);
        }
    }

    /**
     * 加款事务
     * @param walletBO
     */
    @Transactional()
    public void debit(WalletBO walletBO) {
        WalletDO walletDO = walletService.selectWalletByUserId(walletBO.getUserId(), true);
        if (Objects.isNull(walletDO)) {
            throw new BizException(ResultCode.WALLET_INFO_IS_NULL);
        }
        if (WalletStatusEnums.FROZEN.equals(walletDO.getWalletStatus())) {
            throw new BizException(ResultCode.WALLET_STATUS_IS_FROZEN);
        }
        Long newBalance = walletDO.getWalletBalance() + walletBO.getAmount();
        walletBO.setEndingBalance(newBalance);
        walletBO.setWalletNo(walletDO.getWalletNo());
        try {
            accountFlowService.insertAccountFlow(walletBO);
        } catch (DuplicateKeyException e) {
            AccountFlowDO accountFlowDO = accountFlowService.selectAccountFlowByOrderId(walletBO.getOrderId());
            if (!walletBO.getWalletNo().equals(accountFlowDO.getWalletNo())) {
                throw new BizException(ResultCode.ACCOUNT_INCONSISTENT_CORE_PARAMETERS);
            }
            if (!walletBO.getType().equals(accountFlowDO.getType())) {
                throw new BizException(ResultCode.ACCOUNT_INCONSISTENT_CORE_PARAMETERS);
            }
            if (!walletBO.getAmount().equals(accountFlowDO.getAmount())) {
                throw new BizException(ResultCode.ACCOUNT_INCONSISTENT_CORE_PARAMETERS);
            }
            if (!walletBO.getCurrency().equals(accountFlowDO.getCurrency())) {
                throw new BizException(ResultCode.ACCOUNT_INCONSISTENT_CORE_PARAMETERS);
            }
            if (!walletBO.getCounterPartyWalletNo().equals(accountFlowDO.getCounterPartyWalletNo())) {
                throw new BizException(ResultCode.ACCOUNT_INCONSISTENT_CORE_PARAMETERS);
            }
            return;
        }
        int i = walletService.updateWalletBalance(walletBO.getUserId(), newBalance);
        if (i != 1) {
            throw new BizException(ResultCode.BALANCE_UPDATE_FAIL);
        }
    }
}
